home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
alloc_v2
/
sysmem.c
< prev
Wrap
C/C++ Source or Header
|
1987-06-16
|
6KB
|
183 lines
/*****************************************************************************
(c) Copyright 1984,1985,1986,1987, Front Line Software. All Rights Reserved.
SYS_MEM.C
Release 2.0
Written : 12/23/84 Initial Release
Updated : 07/16/87 Added more documenation and DOSALLOC.OBJ
By: Front Line Software Co.
P.O. Box 217
Lowell, Mass 01853
If you find these functions useful please contribute a small donation
( $5.00 ) to help offset the development time. Donations may be sent to
the above address.
If you can't afford the donation we would still like to get some
feedback on the number of people that find this useful and/or comments
on the package. Shareware can be a good deal for both the developers
and the users, but only if it is supported. We can do alot more
with shareware packages if it is shown to be worth our time. Let
us know what you think!
These functions will allow Mark Williams 'C' large model compiler
(and any other 'C' compiler runnning under MS-DOS Operating System)
to ALLOC() and FREE() ALL available system memory.
Currently, Mark Williams will only allow a user to ALLOC 64K of
memory with the Large Model. The user is paying a penalty for using
the large model (slow pointer arithmetic, slower function calls
due to pushing the two values on the stack, and less available
data space due to the double value pointers).
There is no reason why the user should not get the full benefit of
access to ALL of the memory available in the system. These routines
allow the user to get the extra memory!
To adapt to another compiler the only routine which will have to be
changed is the DOSALLOC.ASM routine. The 'entry' and 'exit' code
which preserves the registers needed by the compiler will have to
be updated. Check your compiler manual for how to interface to
assembly language routines. Don't be afraid to try it, it is really
quite simple.
The SALLOC() and SFREE() functions are used with the exact
same parameters as ALLOC and FREE as defined in K & R. These are
the only two points your 'C' program should call. SALLOC will give
you a pointer to the memory you have asked for, and SFREE will
place that memory back into the pool.
Compile SYS_MEM.C and link both SYS_MEM.OBJ and DOSALLOC.OBJ with your
program. Thats it!
We have added DOSALLOC.OBJ to the files as it was pointed out many users
don't have assemblers.
******************************************************************************/
#include <stdio.h>
typedef int ALIGN; /* force alignment on IBM PC */
union header { /* sfree block header */
struct {
union header *ptr; /* to next sfree block */
unsigned int size; /* size of this sfree block */
} s;
ALIGN x; /* force alignment */
};
typedef union header HEADER;
/*****************************************************************************/
/*****************************************************************************/
static HEADER base; /* empty list to get started */
static HEADER *sallocp = NULL; /* last allocated block */
char *salloc(nbytes) /* general-purpose storage allocator */
unsigned nbytes;
{
HEADER *morecore();
HEADER *p,*q;
int nunits;
if ( nbytes > ( 65535 - sizeof(HEADER) ) )
return(NULL);
nunits = 1+(nbytes+sizeof(HEADER)-1)/sizeof(HEADER);
if ((q = sallocp) == NULL) /* no sfree list yet */
{
base.s.ptr = sallocp = q = &base;
base.s.size = 0;
}
for (p=q->s.ptr;; q=p, p=p->s.ptr)
{
if ((long)p->s.size >= (long)nunits) /* big enough */
{
if ((long)p->s.size == (long)nunits) /* exactly */
q->s.ptr = p->s.ptr;
else
{ /* allocate tail end */
p->s.size -= nunits;
p += p->s.size;
p->s.size = nunits;
}
sallocp = q;
return((char *) (p+1));
}
if ((long)p == (long)sallocp) /* wrapped around sfree list */
if (( p = morecore(nunits)) == NULL)
return(NULL); /* none left */
}
}
/*****************************************************************************/
/*****************************************************************************/
#define NSALLOC 2700 /* size of block to get from DOS */
/* ( NSALLOC X 6 ( 6 is the size of HEADER )
= SIZE OF BLOCK REQUESTED ) */
static HEADER *morecore(nu) /* asks system(DOS) for memory */
unsigned nu;
{
char *dosalloc();
char *cp;
HEADER *up;
int rnu;
rnu = NSALLOC * ((nu+NSALLOC-1) / NSALLOC);
cp = dosalloc((unsigned)rnu * sizeof(HEADER));
if ( (long)cp == NULL ) /* no space available */
return(NULL);
up = (HEADER *)cp;
up->s.size = rnu;
sfree((char *) (up + 1));
return(sallocp);
}
/*****************************************************************************/
/*****************************************************************************/
sfree(ap) /* put block ap in sfree list */
char *ap;
{
HEADER *p, *q;
int h,i,j;
h = i = j = 0;
p = (HEADER *)ap - 1; /* point to header */
for (q=sallocp;!((long)p>(long)q && (long)p<(long)q->s.ptr);q=q->s.ptr)
{
if ((h=((long)q >= (long)q->s.ptr)) &&
(((i=((long)p > (long)q)) ||
(j = ((long)p < (long)q->s.ptr)))))
break; /* at one end or the other */
}
if ((long)p+p->s.size == (long)q->s.ptr)/* join to upper nbr */
{
p->s.size += q->s.ptr->s.size;
p->s.ptr = q->s.ptr->s.ptr;
}
else
p->s.ptr = q->s.ptr;
if ((long)q+q->s.size == (long)p) /* join lower nbr */
{
q->s.size += p->s.size;
q->s.ptr = p->s.ptr;
}
else
q->s.ptr = p;
sallocp = q;
}
/*****************************************************************************/